/*****************************************************************************
 * Copyright(c)  2005-2013, mqbest2000@gmail.com
 *
 * Filename:     xsapi.h
 * Version:      1.0
 * Author:       mqbest2000@gmail.com
 * Date:         2012-09-14
 * Description:  1. Include XMPP client and STUN client
 *               2. Just support send xmpp message package
 *
 * Modification History
 *     1.        Version:       1.0
 *               Date:          2012-09-14
 *               Author:        mqbest2000@gmail.com
 *               Modification:  creation
 *****************************************************************************/

#ifndef __XS_API_H_
#define __XS_API_H_

#ifdef __cplusplus
extern  "C"
{
#endif  /* end of #ifdef __cplusplus */

//#define	LINUX_OS
#define	NO_OS

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#if defined(LINUX_OS)
#include <stdarg.h>
#include <ctype.h>
#include <math.h>
#endif

#define XC_TCP_BUF_SIZE 		1500
#define XS_TCP_RBUF_SIZE 		3000
#define XS_MAX_MSG_SIZE     1300
#define XS_JID_SIZE 	      32
#define XS_SER_NAME_SIZE    16
#define XS_DEV_SN_LEN       16
#define XS_CMD_VALUE_LEN    16

#define XS_PRE_SIZE 	      16
#define XS_NO_DATA          0
#define XS_DATA             1
#define XS_PRE_STATE        0x01
#define XS_PRE_CMD          0x02

#define XS_JID_ONLINE       1
#define XS_JID_OFFLINE      0

typedef struct _COM_PORT
{
  unsigned char databit, 
                parity, 
                stopbit, 
                flowctrl;
  unsigned int baudrate;
}COM_PORT;

typedef struct _xsUserCfg_t{
  COM_PORT stCom;
  
  char acHost[XS_JID_SIZE];
  unsigned short usPost;
  
  char acDomain[XS_DEV_SN_LEN];
  char acSn[XS_DEV_SN_LEN];
  
  char acPwd[XS_DEV_SN_LEN];
  
  char acDevJID[XS_JID_SIZE];
  char acDevPeer[XS_DEV_SN_LEN];

  char acMaster[XS_DEV_SN_LEN];
  char acMasterJID[XS_JID_SIZE];
  
  unsigned char ucCmd,
                ucDataFormat;
  unsigned char aucCmdValue[XS_CMD_VALUE_LEN];
}xsUserCfg_t;


typedef int (*pfTcpSend_handler)(unsigned char ucSSLFlag, const unsigned char *pucBuf, unsigned int uiLen);
typedef int (*pfTcpRecv_handler)(unsigned char ucSSLFlag, unsigned char *pucBuf, unsigned int uiSize);

typedef int (*pfUdpSend_handler)(unsigned int uiDstIP, unsigned short usDstPort, const unsigned char *pucBuf, unsigned int uiLen);
typedef int (*pfUdpRecv_handler)(unsigned int uiDstIP, unsigned short usDstPort, unsigned char *pucBuf, unsigned int uiSize);

//#define	 XS_DEBUG
#if defined(XS_DEBUG)

#ifdef NO_OS
extern void my_printf(const char *format, ...);
#define	 xs_print(format, ...) my_printf(format, ##__VA_ARGS__)
#else
#define	 xs_print(format, ...) printf(format, ##__VA_ARGS__)
#endif

#else
#define	 xs_print(format, ...)
#endif

#define	 xs_malloc(type, point, size) {point = (type)malloc(size);}
#define	 xs_free(point)  {free(point);}
#define	 xs_realloc(type, point, size) {point = (type)realloc(point, size);}

enum XC_RET_CODE
{
	XS_OK = 0,       /* function success */
  XS_CONTINUE = 2,
	XS_XML_MUX_PACKAGE =  100,
	XS_XML_LOGIN_SUCCESS =  99,
	XS_XML_NUKNOWN_PACKAGE =  98,
	XS_XML_NOT_COMPLETE = 97,
	XS_XML_LOGOUT = 96,
	
	XS_FAILURE = -1,      /* function fail */
	XS_PARA_ERR = -2,     /* parameter is error */
	XS_MEM_ERR = -3,
	XS_XML_ERR = -4,
	XS_XML_LOGIN_FAILURE = -6,
	XS_XML_AUTH_FAILURE = -7,
	XS_SSL_HANDSHAKE_ERR = -8,
	XS_TCP_BUSY     = -9,
	XS_XML_NOT_MESSAGE = -10,
};

enum XC_LOGIN_STEP{
	XC_OPEN_XML = 0,
	XC_OPEN_STREAM,
	XC_SET_MODE,
	XC_MD5_AUTH,
	XC_TLS_AUTH,
	XC_BINDING,
	XC_SESSION,
	XC_TLS_HANDSHAKE,
	XC_HEARTBEAT,
};

typedef struct _xsCtx_t
{
	unsigned char *pucSBuf; /* The xsapi lib will use this buffer to send data, MUST be more then 256 Bytes */
	unsigned int uiSsize;   /* The buffer size */
	
	unsigned char *pucRBuf; /* The xsapi lib will use this buffer to receive data, MUST be more then 256 Bytes */
	unsigned int uiRSize;   /* The buffer size */
  unsigned int uiRLen;    /* The recv length */
	unsigned char ucSSL;    /* ssl session flag */
	
	/* jid = [ node "@" ] domain [ "/" resource ] */
	const char *pcDomain;   /* Your openfire server name , you can get it from openfire 'Server Information' */
	const char *pcNode;     /* Your nickname in openfire server */
	const char *pcRes;      /* Your resource  */
	const char *pcPwd;      /* Your password */
	unsigned char  ucStep;  /* current work step */
  unsigned char  ucNextStep;  /* next work step */
	 /* This two hooks are work in XMPP client ,socket type is TCP mode*/
	pfTcpSend_handler pfTcpSend;
	pfTcpRecv_handler pfTcpRecv;

	/* This two hooks are work in STUN client, socket type is UPD mode */
	pfUdpSend_handler pfUdpSend;
	pfUdpRecv_handler pfUdpRecv;


}xsCtx_t;

typedef struct _xsMsg_t{
  unsigned char ucFlag;
  unsigned char aucJid[XS_JID_SIZE]; 
  unsigned char aucMsgData[XS_MAX_MSG_SIZE+1]; 
  unsigned int uiMsgLen;
}xsMsg_t;

typedef struct _xsPre_t{
  unsigned char ucFlag;
  unsigned char aucJid[XS_JID_SIZE]; 
  unsigned char aucStatType[XS_PRE_SIZE];
}xsPre_t;

#define	 IPV4_LEN				20

#define	 XS_SSL_DISABLE 0
#define	 XS_SSL_ENABLE 	1
#define	 XS_TLS_MODE    2
#define	 XS_MD5_MODE    3

#define XS_PRI_NS_CMD        "lomo:cmd"

typedef struct _xsNatAttr_t
{
	/* input parameters */
	unsigned int uiSrcIp;
	unsigned int uiDstIp;
	unsigned short usDstPort;

	/* output parameters */
	unsigned char ucType;
	unsigned char aucMapIp[20];
	unsigned int  uiMapIp;
	unsigned short usMapPort;
	
}xsNatAttr_t;

/*****************************************************************************
 * Nama: xsInit
 * Description: initialize xslib 
 * 
 * Input xsCtx_t *pstCtx: xslib ctx
 * Output :
 * 
 * Returns: int: return value see ERROR_CODE
 *****************************************************************************/
int xsInit(xsCtx_t *pstCtx);

/*****************************************************************************
 * Nama: xsXmppLogin
 * Description: The function is login openfire server. 
 *              Do it before, you MUST be connect to openfire server and initialize 'pfTcpSend' and 'pfTcpRecv' point
 * 
 * Input void: 
 * Output :
 * 
 * Returns: int : return value see ERROR_CODE
 *****************************************************************************/
int xsXmppLogin(xsCtx_t *pstCtx);
int xsXmppSSLLogin(xsCtx_t *pstCtx);
int xsXmppConnProc(xsCtx_t *pstCtx, xsMsg_t *pstMsg, xsPre_t *pstPre, xsUserCfg_t *pstCfg);

int xsXmppSendRawString(xsCtx_t *pstCtx, const unsigned char *pcData, unsigned int uiLen);

int xsXmppSendMsg(xsCtx_t *pstCtx, xsMsg_t *pstMsg);
int xsXmppSendPre(xsCtx_t *pstCtx, const char *pcJID, const unsigned char *pcState);

int xsXmppSendcmd(xsCtx_t *pstCtx, const char *pcJID, unsigned char ucCmd, const char *pcValue);
int xsXmppSendRes(xsCtx_t *pstCtx, const char *pcJID, unsigned char ucState);

int xsStunProc(xsCtx_t *pstCtx, xsNatAttr_t *pstNatAttr);

int xsXmppLogout(xsCtx_t *pstCtx);

int xsTerm(xsCtx_t *pstCtx);

#ifdef __cplusplus
}
#endif  /* end of #ifdef __cplusplus */

#endif /*end of __XS_API_H_*/

